package com.ledijiaoyu.autogate.base;

import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.List;

import cn.dinkevin.xui.util.ListUtil;
import cn.dinkevin.xui.util.StringUtil;

/**
 * Create with Android Studio
 * Author: chengpengfei
 * Date: 2018/5/21
 * Time: 7:40 PM
 * Description: 闸机数据包，本属性值中所有字符串类在转换数据
 */
public class AutoGatePacket {

    public static final char head = 'H';                    // 固定数据包头
    protected String machineCode = "001";                   // 机号，默认为001
    protected String command;                               // 命令
    protected List<String> argus = new ArrayList<>();       // 参数数据
    protected int crc;                                      // 异或校验
    public static final char tail = 0x0d;                   // 数据包尾

    protected ByteBuffer mBuffer = ByteBuffer.allocate(200);        // 默认缓存数据长度为 100
    protected int mPoint = 0;


    public static final int POSITION_HEAD = 0;
    public static final int POSITION_MACHINE_CODE = 1;
    public static final int POSITION_COMMAND = 4;
    public static final int POSITION_ARGUS_COUNT = 7;


    /**
     * 写入到缓存中
     * @param data
     */
    protected void writeBuffer(char data){
        byte temp = (byte)(data & 0xff);
        mBuffer.put(mPoint++,temp);
    }


    /**
     * 写入到缓存中
     * @param data
     */
    protected void writeBuffer(char[] data){
        if(null != data && data.length > 0){
            for(int i = 0;i < data.length;i++){
                byte temp = (byte)(data[i] & 0xff);
                mBuffer.put(mPoint++,temp);
            }
        }
    }


    /**
     * 写入到缓存中
     * @param data
     */
    protected void writeBuffer(byte data){
        mBuffer.put(mPoint++,data);
    }


    /**
     * 写入数据包头
     */
    protected void fillHead(){
        mBuffer.clear();
        mPoint = POSITION_HEAD;
        writeBuffer(head);
    }


    /**
     * 填充机器码
     */
    protected void fillMachineCode(){
        mPoint = POSITION_MACHINE_CODE;
        writeBuffer(machineCode);
    }


    /**
     * 写入指令
     */
    protected void fillCommand(){
        mPoint = POSITION_COMMAND;
        writeBuffer(command);
    }


    /**
     * 写入参数
     */
    protected void fillArgus(){

        // 写入参数数量
        int argusCount = argus.size();
        char c1,c2;
        int temp;
        if(argusCount < 100){
            temp = argusCount / 10;
            c1 = Integer.toString(temp).toUpperCase().charAt(0);

            temp = argusCount % 10;
            c2 = Integer.toString(temp).toUpperCase().charAt(0);
        }else{
            temp = argusCount / 10;
            c1 = Integer.toString(temp).toUpperCase().charAt(0);

            temp = argusCount % 10;
            c2 = Integer.toString(temp).toUpperCase().charAt(0);
        }
        mPoint = POSITION_ARGUS_COUNT;
        writeBuffer(c1);
        writeBuffer(c2);

        // 写入参数数据
        ListUtil.foreach(argus,arg -> {
            char[] t_asicc = arg.toCharArray();
            writeBuffer(t_asicc);
        });
    }


    /**
     * 计算异或值
     */
    protected void fillCRC(){

        int crc = mBuffer.get(0) & 0xff;
        for(int i = 1; i < mPoint;i++){
            crc ^= (mBuffer.get(i) & 0xff);
        }
        String crcHex = Integer.toHexString(crc);
        if(StringUtil.length(crcHex) < 2){
            crcHex = "0" + crcHex;
        }
        char[] temp = crcHex.toUpperCase().toCharArray();
        writeBuffer(temp[0]);
        writeBuffer(temp[1]);
    }


    /**
     * 写入尾巴
     */
    protected void fillTail(){
        writeBuffer(tail);
    }


    /**
     * 写入数据到缓存
     * @param data（只是数字或者字母）
     */
    protected void writeBuffer(String data){
        if(StringUtil.isEmpty(data)) return;
        for(int i = 0; i < data.length();i++){
            char temp = data.charAt(i);
            writeBuffer(temp);
        }
    }


    public AutoGatePacket() {}


    /**
     * 构造器
     * @param command
     * @param argus
     */
    public AutoGatePacket(String command, List<String> argus) {
        this.command = command;
        this.argus.clear();
        this.argus.addAll(argus);
    }


    /**
     * 构造器
     * @param machineCode
     * @param command
     * @param argus
     */
    public AutoGatePacket(String machineCode, String command, List<String> argus) {
        this.machineCode = machineCode;
        this.command = command;
        this.argus.clear();
        this.argus.addAll(argus);
    }


    /**
     * 压缩填充数据包
     */
    protected void compressPacket(){
        fillHead();             // 填充数据包头部
        fillMachineCode();      // 填充数据包机器码
        fillCommand();          // 填充数据包命令
        fillArgus();            // 填充数据包参数
        fillCRC();              // 填充数据 CRC 校验值
        fillTail();             // 填充数据包尾巴
    }


    /**
     * 将数据包内容输出到 Byte 数组
     * @return
     */
    public byte[] output(){
        byte[] output = new byte[mPoint];
        mBuffer.get(output);
        return output;
    }


    public static char getHead() {
        return head;
    }


    public String getMachineCode() {
        return machineCode;
    }


    public String getCommand() {
        return command;
    }


    protected void setCommand(String command){
        this.command = command;
    }


    public int getArgusCount() {
        return argus.size();
    }


    public List<String> getArgus() {
        return argus;
    }


    public int getCrc() {
        return crc;
    }


    public static char getTail() {
        return tail;
    }
}
